This is a source of the WPF Demo application for OPC-UA PubSub that ships with OPC Data Client. The application offers a selection of ready-made settings for various OPC UA PubSub subscription choices, and also offers a rich user interface to specify custom settings. It then allows to subscribe to datasets and display the received data dynamically.
The main form:
// $Header: $ // Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved. // // Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . // OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp . // Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own // a commercial license in order to use Online Forums, and we reply to every post. using System; using System.Diagnostics; using System.Drawing; using System.Reflection; using System.Windows.Forms; using OpcLabs.EasyOpc.UA.PubSub; using OpcLabs.EasyOpc.UA.PubSub.Extensions; using OpcLabs.EasyOpc.UA.PubSub.Engine; using OpcLabs.EasyOpc.UA.PubSub.OperationModel; // ReSharper disable InconsistentNaming // ReSharper disable StringLiteralTypo namespace EasyOpcUAPubSubDemo { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private bool _subscribed; /// <summary> /// The user has pressed the "About" button. Show a message box with information about the executing assembly. /// </summary> private void aboutButton_Click(object sender, EventArgs e) { MessageBox.Show(this, Assembly.GetExecutingAssembly().FullName, "Assembly Name", MessageBoxButtons.OK, MessageBoxIcon.Information); } /// <summary> /// Event handler for the <see cref="EasyUASubscriberCore.DataSetMessage"/> event. It is invoked for every received /// dataset. We display the dataset data received (or the error) on the form. /// </summary> private void easyUASubscriber1_DataSetMessage(object sender, EasyUADataSetMessageEventArgs e) { Debug.Assert(!(e is null)); errorTextBox.BackColor = e.Succeeded ? SystemColors.Control : Color.Orange; errorTextBox.Text = e.Succeeded ? "" : e.Exception?.GetBaseException().Message; uaDataSetDataControl1.Value = e.DataSetData; } /// <summary> /// Unsubscribe from the dataset whenever the form is closing. /// </summary> private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { Subscribed = false; } /// <summary> /// When the form loads, select the ready-made settings for UADP over MQTT. /// </summary> private void MainForm_Load(object sender, EventArgs e) { readyMadeSettingsComboBox.SelectedIndex = 4; } /// <summary> /// Act upon a change in the "subscribed" status, i.e. perform the actual subscribe or unsubscribe. Also, enable or /// disable controls on the screen based on the new status. /// </summary> private void OnSubscribedChanged() { if (Subscribed) { if (!(SubscribeDataSetArguments is null)) easyUASubscriber1.SubscribeDataSet(SubscribeDataSetArguments); } else easyUASubscriber1.UnsubscribeAllDataSets(); readyMadeSettingsComboBox.Enabled = !Subscribed; subscribeButton.Enabled = !Subscribed; unsubscribeButton.Enabled = Subscribed; } /// <summary> /// The user has selected a different set of read-made settings. Change the arguments for dataset subscription in /// accordance with the selected settings. /// </summary> private void readyMadeSettingsComboBox_SelectedIndexChanged(object sender, EventArgs e) { UASubscribeDataSetArguments subscribeDataSetArguments = null; string info = null; switch (readyMadeSettingsComboBox.SelectedIndex) { case 0: subscribeDataSetArguments = UASubscribeDataSetArguments.Default; break; case 1: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { CommunicationParameters = {BrokerDataSetReaderTransportParameters = {QueueName = "opcuademo/json"}}, ConnectionDescriptor = { ResourceAddress = "mqtt://opcua-pubsub.demo-this.com", TransportProfileUriString = UAPubSubTransportProfileUriStrings.MqttJson }, Filter = { //DataSetWriterDescriptor = 4, // not contained in the message PublisherId = { ExternalValue = "32" } } } }; break; case 2: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { ConnectionDescriptor = { ResourceAddress = "opc.eth://FF-FF-FF-FF-FF-FF", TransportProfileUriString = UAPubSubTransportProfileUriStrings.EthUadp }, Filter = { DataSetWriterDescriptor = 4, PublisherId = { ExternalValue = (Decimal)31 } } } }; try { subscribeDataSetArguments.DataSetSubscriptionDescriptor.ConnectionDescriptor .UseEthernetCaptureFile("UADemoPublisher-Ethernet.pcap"); } catch (Exception exception) { errorTextBox.BackColor = Color.Orange; errorTextBox.Text = exception.GetBaseException().Message; } break; case 3: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { ConnectionDescriptor = { ResourceAddress = "opc.eth://FF-FF-FF-FF-FF-FF", TransportProfileUriString = UAPubSubTransportProfileUriStrings.EthUadp }, Filter = { DataSetWriterDescriptor = 4, PublisherId = { ExternalValue = (Decimal)31 } } } }; info = "In order to produce network messages for this demo, run the UADemoPublisher tool with the -eth switch. In some cases, you may have to specify the interface name to be used. Additional software may be needed."; break; case 4: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { CommunicationParameters = {BrokerDataSetReaderTransportParameters = {QueueName = "opcuademo/uadp/none"}}, ConnectionDescriptor = { ResourceAddress = "mqtt://opcua-pubsub.demo-this.com", TransportProfileUriString = UAPubSubTransportProfileUriStrings.MqttUadp }, Filter = { DataSetWriterDescriptor = 4, PublisherId = { ExternalValue = "32" } } } }; break; case 5: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { ConnectionDescriptor = { ResourceAddress = "opc.udp://239.0.0.1", TransportProfileUriString = UAPubSubTransportProfileUriStrings.UdpUadp }, Filter = { DataSetWriterDescriptor = 4, PublisherId = { ExternalValue = (Decimal)31 } } } }; info = "In order to produce network messages for this demo, run the UADemoPublisher tool. In some cases, you may have to specify the interface name to be used (on the publisher or subscriber side, or both)."; break; case 6: subscribeDataSetArguments = new UASubscribeDataSetArguments { DataSetSubscriptionDescriptor = { ConnectionDescriptor = { Name = "FixedLayoutConnection" }, Filter = { DataSetWriterDescriptor = { Name = "SimpleWriter" }, WriterGroupDescriptor = { Name = "FixedLayoutGroup" } }, ResolverDescriptor = { PublisherFileResourceDescriptor = "UADemoPublisher-Default.uabinary", ResolverKind = UAPubSubResolverKind.PublisherFile } } }; info = "In order to produce network messages for this demo, run the UADemoPublisher tool. In some cases, you may have to specify the interface name to be used (on the publisher or subscriber side, or both)."; break; } SubscribeDataSetArguments = subscribeDataSetArguments; infoLabel.Visible = !string.IsNullOrEmpty(info); infoLabel.Text = info; } /// <summary> /// The user has pressed the "Subscribe" button. /// </summary> private void subscribeButton_Click(object sender, EventArgs e) { Subscribed = true; } /// <summary> /// Determines whether we are currently subscribed to a dataset. Setting this property creates or removes the /// dataset subscription. /// </summary> private bool Subscribed { get => _subscribed; set { if (value == _subscribed) return; _subscribed = value; OnSubscribedChanged(); } } /// <summary> /// Get the arguments for dataset subscription from the control on the form, or set them to the control. /// </summary> private UASubscribeDataSetArguments SubscribeDataSetArguments { get => (UASubscribeDataSetArguments)subscribeDataSetArgumentsControl.GetControlValue(); set => subscribeDataSetArgumentsControl.SetControlValue(value); } /// <summary> /// The user has pressed the "Unsubscribe" button. /// </summary> private void unsubscribeButton_Click(object sender, EventArgs e) { Subscribed = false; } } }
' $Header: $ ' Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved. ' ' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . ' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET . ' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own ' a commercial license in order to use Online Forums, and we reply to every post. Imports System.Reflection Imports OpcLabs.EasyOpc.UA.PubSub Imports OpcLabs.EasyOpc.UA.PubSub.Engine Imports OpcLabs.EasyOpc.UA.PubSub.Extensions Imports OpcLabs.EasyOpc.UA.PubSub.OperationModel <Assembly: CLSCompliant(True)> ' ReSharper disable InconsistentNaming ' ReSharper disable StringLiteralTypo Partial Public Class MainForm Inherits Form Public Sub New() InitializeComponent() End Sub Private _subscribed As Boolean ''' <summary> ''' The user has pressed the "About" button. Show a message box with information about the executing assembly. ''' </summary> Private Sub aboutButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles aboutButton.Click MessageBox.Show(Me, Assembly.GetExecutingAssembly().FullName, "AssemblyName", MessageBoxButtons.OK, MessageBoxIcon.Information) End Sub ''' <summary> ''' Event handler for the <see cref="EasyUASubscriberCore.DataSetMessage"/> event. It is invoked for every received ''' dataset. We display the dataset data received (or the error) on the form. ''' </summary> Private Sub easyUASubscriber1_DataSetMessage(ByVal sender As Object, ByVal e As EasyUADataSetMessageEventArgs) Handles easyUASubscriber1.DataSetMessage Debug.Assert(e IsNot Nothing) errorTextBox.BackColor = If(e.Succeeded, SystemColors.Control, Color.Orange) errorTextBox.Text = If(e.Succeeded, "", e.Exception?.GetBaseException().Message) uaDataSetDataControl1.Value = e.DataSetData End Sub ''' <summary> ''' Unsubscribe from the dataset whenever the form is closing. ''' </summary> Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing Subscribed = False End Sub ''' <summary> ''' When the form loads, select the ready-made settings for UADP over MQTT. ''' </summary> Private Sub MainForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load readyMadeSettingsComboBox.SelectedIndex = 4 End Sub ''' <summary> ''' Act upon a change in the "subscribed" status, i.e. perform the actual subscribe Or unsubscribe. Also, enable or ''' disable controls on the screen based on the new status. ''' </summary> Private Sub OnSubscribedChanged() If Subscribed Then If SubscribeDataSetArguments IsNot Nothing Then easyUASubscriber1.SubscribeDataSet(SubscribeDataSetArguments) End If Else easyUASubscriber1.UnsubscribeAllDataSets() End If readyMadeSettingsComboBox.Enabled = Not Subscribed subscribeButton.Enabled = Not Subscribed unsubscribeButton.Enabled = Subscribed End Sub ''' <summary> ''' The user has selected a different set of read-made settings. Change the arguments for dataset subscription in ''' accordance with the selected settings. ''' </summary> Private Sub readyMadeSettingsComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles readyMadeSettingsComboBox.SelectedIndexChanged Dim subscribeDataSetArguments2 As UASubscribeDataSetArguments = Nothing Dim info As String = Nothing Select Case readyMadeSettingsComboBox.SelectedIndex Case 0 subscribeDataSetArguments2 = UASubscribeDataSetArguments.Default Case 1 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.CommunicationParameters.BrokerDataSetReaderTransportParameters.QueueName = "opcuademo/json" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.ResourceAddress = "mqtt://opcua-pubsub.demo-this.com" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.TransportProfileUriString = UAPubSubTransportProfileUriStrings.MqttJson 'subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor = New UADataSetWriterDescriptor(4) ' not contained in the message subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.PublisherId.ExternalValue = "32" Case 2 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.ResourceAddress = "opc.eth://FF-FF-FF-FF-FF-FF" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.TransportProfileUriString = UAPubSubTransportProfileUriStrings.EthUadp subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor = New UADataSetWriterDescriptor(4) subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.PublisherId.ExternalValue = CDec(31) Try subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.UseEthernetCaptureFile("UADemoPublisher-Ethernet.pcap") Catch exception As Exception errorTextBox.BackColor = Color.Orange errorTextBox.Text = exception.GetBaseException().Message End Try Case 3 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.ResourceAddress = "opc.eth://FF-FF-FF-FF-FF-FF" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.TransportProfileUriString = UAPubSubTransportProfileUriStrings.EthUadp subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor = New UADataSetWriterDescriptor(4) subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.PublisherId.ExternalValue = CDec(31) info = "In order to produce network messages for this demo, run the UADemoPublisher tool with the -eth switch. In some cases, you may have to specify the interface name to be used. Additional software may be needed." Case 4 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.CommunicationParameters.BrokerDataSetReaderTransportParameters.QueueName = "opcuademo/uadp/none" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.ResourceAddress = "mqtt://opcua-pubsub.demo-this.com" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.TransportProfileUriString = UAPubSubTransportProfileUriStrings.MqttUadp subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor = New UADataSetWriterDescriptor(4) subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.PublisherId.ExternalValue = "32" Case 5 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.ResourceAddress = "opc.udp://239.0.0.1" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.TransportProfileUriString = UAPubSubTransportProfileUriStrings.UdpUadp subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor = New UADataSetWriterDescriptor(4) subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.PublisherId.ExternalValue = CDec(31) info = "In order to produce network messages for this demo, run the UADemoPublisher tool. In some cases, you may have to specify the interface name to be used (on the publisher or subscriber side, or both)." Case 6 subscribeDataSetArguments2 = New UASubscribeDataSetArguments() subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ConnectionDescriptor.Name = "FixedLayoutConnection" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.DataSetWriterDescriptor.Name = "SimpleWriter" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.Filter.WriterGroupDescriptor.Name = "FixedLayoutGroup" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ResolverDescriptor.PublisherFileResourceDescriptor = "UADemoPublisher-Default.uabinary" subscribeDataSetArguments2.DataSetSubscriptionDescriptor.ResolverDescriptor.ResolverKind = UAPubSubResolverKind.PublisherFile info = "In order to produce network messages for this demo, run the UADemoPublisher tool. In some cases, you may have to specify the interface name to be used (on the publisher or subscriber side, or both)." End Select SubscribeDataSetArguments = subscribeDataSetArguments2 infoLabel.Visible = Not String.IsNullOrEmpty(info) infoLabel.Text = info End Sub ''' <summary> ''' The user has pressed the "Subscribe" button. ''' </summary> Private Sub subscribeButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles subscribeButton.Click Subscribed = True End Sub ''' <summary> ''' Determines whether we are currently subscribed to a dataset. Setting this property creates or removes the ''' dataset subscription. ''' </summary> Private Property Subscribed() As Boolean Get Return _subscribed End Get Set(ByVal value As Boolean) If value = _subscribed Then Return End If _subscribed = value OnSubscribedChanged() End Set End Property ''' <summary> ''' Get the arguments for dataset subscription from the control on the form, or set them to the control. ''' </summary> Private Property SubscribeDataSetArguments() As UASubscribeDataSetArguments Get Return CType(subscribeDataSetArgumentsControl.GetControlValue(), UASubscribeDataSetArguments) End Get Set(ByVal value As UASubscribeDataSetArguments) subscribeDataSetArgumentsControl.SetControlValue(value) End Set End Property ''' <summary> ''' The user has pressed the "Unsubscribe" button. ''' </summary> Private Sub unsubscribeButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles unsubscribeButton.Click Subscribed = False End Sub End Class
Copyright © 2004-2024 CODE Consulting and Development, s.r.o., Plzen. All rights reserved.
Documentation Home, Send Documentation Feedback. Technical Support